#!/usr/bin/env python
import os
from string import *
from subprocess import call
from CLI_strings import *

# Main program function
def main():
    print('===================================================================\
============');
    print(center('Parallel Reed-Solomon Decoder Simulation',80));
    print('');
    print(center('Created by:',80));
    print(center('Tom Chatt (tjc42@cornell.edu)',80));
    print(center('Allison Smyth (aps243@cornell.edu)',80));
    print('');
    print('===================================================================\
============');
    print('''
    Enter commands at the prompt to set up and run the simulator and display 
    the results.  Type "help" at any time to see a list of all available 
    commands.  Type "help <command>" at any time to see a details for a 
    particular command.
    ''');

    # Initialize all of the system parameters
    help = False;
    verbose = False;
    test = False;

    m = '-1';
    t = '-1';
    num_DEs = '-1';
    decoder_mode = '';
    ifile = '';
    dfile = '';
    ofile = '';
    gen_data = False;
    no_run = False;
    data_length = '-1';
    e_prob = '-1';
    e_per_word = '-1';
    e_pmf = '';
    
    # Main program loop
    while(1):
        # Read from the command line
        user_input = raw_input("RS>> ");

        # Remove duplicate whitespace
        user_input = ' '.join(user_input.split());
       
        # Process commands
        if lower(user_input) == 'run':
            
            command_list = ['../bin/RS'];

            if help:
                command_list.append('-h');

            if verbose:
                command_list.append('-v');

            if test:
                command_list.append('-T');

            if m != '-1':
                command_list.append('-m '+m);

            if t != '-1':
                command_list.append('-t '+t);

            if num_DEs != '-1':
                command_list.append('-D '+num_DEs);

            if decoder_mode != '':
                if decoder_mode == 'serial':
                    command_list.append('-M '+MODE_SERIAL);
                elif decoder_mode == 'pthread':
                    command_list.append('-M '+MODE_PTHREAD);
                elif decoder_mode == 'openMP static allocation':
                    command_list.append('-M '+MODE_OPENMP_STATIC);
                elif decoder_mode == 'openMP guided allocation':
                    command_list.append('-M '+MODE_OPENMP_GUIDED);
                elif decoder_mode == 'openMP dynamic allocation':
                    command_list.append('-M '+MODE_OPENMP_DYNAMIC);

            if ifile != '':
                command_list.append('-i '+ifile);

            if dfile != '':
                command_list.append('-f '+dfile);

            if ofile != '':
                command_list.append('-o '+ofile);

            if gen_data:
                command_list.append('-g');

            if no_run:
                command_list.append('-N');

            if data_length != '-1':
                command_list.append('-l '+data_length);

            if e_prob != '-1':
                command_list.append('-p '+e_prob);

            if e_per_word != '-1':
                command_list.append('-e '+e_per_word);

            if e_pmf != '':
                command_list.append('-d '+e_pmf);
           
            print("""Issuing command '"""+" ".join(command_list)+"'...");

            # Call the C program         
            os.system(' '.join(command_list));

            print("Done.");

        elif lower(user_input) == '':
            pass;

        elif lower(user_input) == 'exit':
            break;
        
        elif lower(user_input) == 'help':
            print(COMMAND_LIST);

        elif lower(user_input) == 'help help':
            print(COMMAND_HELP);

        elif lower(user_input) == 'help exit':
            print(COMMAND_EXIT);

        elif lower(user_input) == 'help clear':
            print(COMMAND_CLEAR);

        elif lower(user_input) == 'help properties':
            print(COMMAND_PROPERTIES);

        elif lower(user_input) == 'help run':
            print(COMMAND_RUN);

        elif lower(user_input) == 'help set':
            print(COMMAND_SET);

        elif lower(user_input) == 'help view':
            print(COMMAND_VIEW);

        elif lower(user_input) == 'view all':
            print("\n    Property   |   Type   |   Value");
            print("    -------------------------------");
            print("    help:         Bool       %s" % help);
            print("    verbose:      Bool       %s" % verbose);
            print("    test:         Bool       %s" % test);
            print("    m:            Int        %s" % m);
            print("    t:            Int        %s" % t);
            print("    num_DEs:      Int        %s" % num_DEs);
            print("    decoder_mode: String     %s" % decoder_mode);
            print("    ifile:        String     %s" % ifile);
            print("    dfile:        String     %s" % dfile);
            print("    ofile:        String     %s" % ofile);
            print("    gen_data:     Bool       %s" % gen_data);
            print("    no_run:       Bool       %s" % no_run);
            print("    data_length:  Int        %s" % data_length);
            print("    e_prob:       Double     %s" % e_prob);
            print("    e_per_word:   Int        %s" % e_per_word);
            print("    e_pmf:        String     %s" % e_pmf);
            print('');

        elif lower(user_input) == 'clear all':
            confirm = raw_input("\nClear all properties - are you sure? (Y/N) ");
            confirm = ' '.join(split(confirm));
            while not (lower(confirm) == 'y' or lower(confirm) == 'n'):
                confirm = raw_input("Invalid response.  Please enter Y or N: ");
                confirm = ' '.join(split(confirm));

            if lower(confirm) == 'y':
                # Reset parameters to defaults
                help = False;
                verbose = False;
                test = False;

                m = '-1';
                t = '-1';
                num_DEs = '-1';

                ifile = '';

                ofile = '';
                gen_data = False;
                no_run = False;
                data_length = '-1';
                e_prob = '-1';
                e_per_word = '-1';
                e_pmf = '';
                interleave = '-1';
                print("All properties reset to default values.\n");

        elif lower(user_input) == 'properties':
            print(PROPERTY_LIST);
        
        # clear / set / view for 'help'
        elif lower(user_input) == 'clear help':
            help = False;

        elif lower(user_input) == 'set help':
            if help:
                help = False;
            else:
                help = True;

        elif lower(user_input) == 'view help':
            print('help: %s\n' % `help`);

        # clear / set / view for 'verbose'
        elif lower(user_input) == 'clear verbose':
            verbose = False;

        elif lower(user_input) == 'set verbose':
            if verbose:
                verbose = False;
            else:
                verbose = True;

        elif lower(user_input) == 'view verbose':
            print('verbose: %s\n' % `help`);

        # clear / set / view for 'test'
        elif lower(user_input) == 'clear test':
            test = False;

        elif lower(user_input) == 'set test':
            if test:
                test = False;
            else:
                test = True;

        elif lower(user_input) == 'view test':
            print('test: %s\n' % `help`);

        # clear / set / view for 'm'
        elif lower(user_input) == 'clear m':
            m = -1;

        elif lower(user_input) == 'set m':
            value = raw_input('Enter the new value of m: ');
            value = ' '.join(split(value));
            m = value;

        elif lower(user_input) == 'view m':
            print('m: %s\n' % m);

        # clear / set / view for 't'
        elif lower(user_input) == 'clear t':
            t = -1;

        elif lower(user_input) == 'set t':
            value = raw_input('Enter the new value of t: ');
            value = ' '.join(split(value));
            t = value;

        elif lower(user_input) == 'view t':
            print('t: %s\n' % t);

        # clear / set / view for 'num_DEs'
        elif lower(user_input) == 'clear num_des':
            num_DEs = -1;

        elif lower(user_input) == 'set num_des':
            value = raw_input('Enter the new value of num_DEs: ');
            value = ' '.join(split(value));
            num_DEs = value;

        elif lower(user_input) == 'view num_des':
            print('num_DEs: %s\n' % num_DEs);            

        # clear / set / view for 'decoder_mode'
        elif lower(user_input) == 'clear decoder_mode':
            decoder_mode = '';

        elif lower(user_input) == 'set decoder_mode':
            value = raw_input('Choose a decoder mode:\n(S)erial, (P)thread, (O)penMPstatic, OpenMP(D)ynamic, OpenMP(G)uided or C to cancel: ');
            v = lower(value);
            while not (v == 's' or v == 'p' or v == 'o' or v == 'd' or v == 'g' or v == 'c'):
                if not (v == 'c'):
                    print("Error: invalid mode.");
                    value = raw_input('Choose a decoder mode:\n(S)erial, (P)thread, (O)penMPstatic, OpenMP(D)ynamic, OpenMP(G)uided or C to cancel: ');
                    v = lower(value);

            if not v == 'c':
                if v == 's':
                    decoder_mode = 'serial';
                elif v == 'p':
                    decoder_mode = 'pthread';
                elif v == 'o':
                    decoder_mode = 'openMP static allocation';
                elif v == 'd':
                    decoder_mode = 'openMP dynamic allocation';
                elif v == 'g':
                    decoder_mode = 'openMP guided allocation';
            
        # clear / set / view for 'ifile'
        elif lower(user_input) == 'clear ifile':
            ifile = '';

        elif lower(user_input) == 'set ifile':
            value = raw_input('Enter the new value of ifile: ');
            ifile = value;

        elif lower(user_input) == 'view ifile':
            print('ifile: %s\n' % ifile);

        # clear / set / view for 'dfile'
        elif lower(user_input) == 'clear dfile':
            dfile = '';

        elif lower(user_input) == 'set dfile':
            value = raw_input('Enter the new value of dfile: ');
            dfile = value;

        elif lower(user_input) == 'view dfile':
            print('dfile: %s\n' % dfile);

        # clear / set / view for 'ofile'
        elif lower(user_input) == 'clear ofile':
            ifile = '';

        elif lower(user_input) == 'set ofile':
            value = raw_input('Enter the new value of ofile: ');
            ofile = value;

        elif lower(user_input) == 'view ofile':
            print('ifile: %s\n' % ofile);

        # clear / set / view for 'gen_data'
        elif lower(user_input) == 'clear gen_data':
            gen_data = False;

        elif lower(user_input) == 'set gen_data':
            if gen_data:
                gen_data = False;
            else:
                gen_data = True;

        elif lower(user_input) == 'view gen_data':
            print('gen_data: %s\n' % `gen_data`);

        # clear / set / view for 'no_run'
        elif lower(user_input) == 'clear no_run':
            no_run = False;

        elif lower(user_input) == 'set no_run':
            if no_run:
                no_run = False;
            else:
                no_run = True;

        elif lower(user_input) == 'view no_run':
            print('no_run: %s\n' % `no_run`);

        # clear / set / view for 'data_length'
        elif lower(user_input) == 'clear data_length':
            no_run = '-1';

        elif lower(user_input) == 'set data_length':
            value = raw_input('Enter the new value of data_length: ');
            value = ' '.join(split(value));
            data_length = value;

        elif lower(user_input) == 'view data_length':
            print('data_length: %s\n' % data_length);

        # clear / set / view for 'e_prob'
        elif lower(user_input) == 'clear e_prob':
            e_prob = '-1';

        elif lower(user_input) == 'set e_prob':
            value = raw_input('Enter the new value of e_prob: ');
            value = ' '.join(split(value));
            e_prob = value;

        elif lower(user_input) == 'view e_prob':
            print('e_prob: %s\n' % e_prob);

        # clear / set / view for e_per_word
        elif lower(user_input) == 'clear e_per_word':
            e_per_word = '-1';

        elif lower(user_input) == 'set e_per_word':
            value = raw_input('Enter the new value of e_per_word: ');
            value = ' '.join(split(value));
            e_per_word = value;

        elif lower(user_input) == 'view e_per_word':
            print('e_per_word: %s\n' % e_per_word);

        # clear / set / view for e_pmf
        elif lower(user_input) == 'clear e_pmf':
            e_pmf = '';

        elif lower(user_input) == 'set e_pmf':
            value = raw_input('Enter the new value of e_pmf: ');
            e_pmf = value;

        elif lower(user_input) == 'view e_pmf':
            print('e_pmf: %s\n' % e_pmf);

        # clear / set / view for interleave
        elif lower(user_input) == 'clear interleave':
            interleave = False;

        elif lower(user_input) == 'set interleave':
            if interleave:
                interleave = False;
            else:
                interleave = True;

        elif lower(user_input) == 'view interleave':
            print('interleave: %s\n' % interleave);
        else:
            print("""Error: unrecognized command string '%s'.  Type "help" for\
 more information.\n""" % user_input);

# Launch the main function
if __name__ == "__main__":
    main();
